/***********************************************************************************
Copy right:	    Coffee Tech.
Author:         jiaoyue
Date:           2019.8.1
Description:    log组件接口
***********************************************************************************/
#include <log_utils.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

#define DEFAULT_DBG_LEVEL  7    //如果log中没有指定级别，则默认是此级别，无实际作用，无需修改
static int dbg_limit = 7;  //小于此级别的会输出，set_dbg_level即设置此参数，只有log中级别小于此级别才会输出

static void log_str_handle(const char *str_tmp);
static void set_dbg_limit(const char *buf);

long get_sys_runtime(int type)
{
	struct timespec times = {0, 0};
	long time;

	clock_gettime(CLOCK_MONOTONIC, &times);

	if (1 == type)
	{
		time = times.tv_sec;
	}
	else
	{
		time = times.tv_nsec / 1000000;
	}

	// printf("time = %ld\n", time);
	return time;
}

/**
 * @brief 处理字符串，发给服务器处理
 */
int log_std(const char *format, ...)
{
    char str_tmp[MAX_LOG_BUF_LEN];
    va_list arg;
    int len;

	va_start(arg, format);
    len = vsnprintf(str_tmp, MAX_LOG_BUF_LEN, format, arg);
	va_end(arg);
	str_tmp[len] = '\0';

    log_str_handle(str_tmp);

	return 0;
}

/**
 * @brief 设置打印级别
 * @param APP_INFO等
 */
void set_dbg_level(const char *limit)
{
    set_dbg_limit(limit);
}

static int log_handle(const char *str_tmp)
{
    const char *tmp;
    int dbglevel = DEFAULT_DBG_LEVEL;

    tmp = str_tmp;

    //printf("<4><1><5>");
    // 根据打印级别决定是否打印
    if((str_tmp[0] == '<') && (str_tmp[2] == '>')){
        dbglevel = str_tmp[1] - '0';
        if (dbglevel >= 0 && dbglevel <= 9){
            tmp = tmp + 3;
        }
    }

    if (dbglevel > dbg_limit){
        return -1;
    }

    printf("%s", tmp);

    return 0;
}

static int log_std_handle(const char *str_tmp)
{
    const char *tmp;
    int dbglevel = DEFAULT_DBG_LEVEL;

    tmp = str_tmp;

    //printf("<4><1><5>");
    // 根据打印级别决定是否打印
    if((str_tmp[0] == '<') && (str_tmp[2] == '>')){
        dbglevel = str_tmp[1] - '0';
        if (dbglevel >= 0 && dbglevel <= 9){
            tmp = tmp + 3;
        }
    }

    if (dbglevel > dbg_limit){
        return -1;
    }

    char str_final[MAX_LOG_BUF_LEN];
    switch (dbglevel) {
    case 5:
        sprintf(str_final, "\033[36m%s\033[0m\r\n", tmp);
        break;
    case 4:
        sprintf(str_final, "\033[33m%s\033[0m\r\n", tmp);
        break;
    case 3:
        sprintf(str_final, "\033[31m%s\033[0m\r\n", tmp);
        break;
    case 2:
        sprintf(str_final, "\033[35m%s\033[0m\r\n", tmp);
        break;
    case 1:
        sprintf(str_final, "\033[35m%s\033[0m\r\n", tmp);
        break;
    case 0:
        sprintf(str_final, "\033[35m%s\033[0m\r\n", tmp);
        break;
    default:
        sprintf(str_final, "%s\r\n", tmp);
        break;
    }

    printf("%s", str_final);

    return 0;
}


/**
 * @brief 初步处理
 * @param str_tmp
 * @return
 */
static void log_str_handle(const char *str_tmp)
{
    //printf("recv from client = %s\n", str_tmp);

    if(strncmp(str_tmp, LOG_STD_FLAG, 3) == 0){ //标准log信息
        log_std_handle(str_tmp + 3);
    }else if(strncmp(str_tmp, LOG_ORG_FLAG, 3) == 0){ //简要log信息
        log_handle(str_tmp + 3);
    }else{

    }
}

void set_dbg_limit(const char *buf)
{
    if((buf[0] == '<') && (buf[2] == '>')){
        int dbglevel = buf[1] - '0';
        if(dbglevel >= 0 && dbglevel <= 7){
            dbg_limit = dbglevel;
        }
    }
}

/************************只针对自定义console*****************************/
static int console_fd = -1;

/**
 * @brief 初始化console口，只针对调试非标准输出情况
 * @param con_name 类似与/dev/pts/1之类
 * @return 0 -1
 */
int log_console_init(const char *con_name)
{
    console_fd = open(con_name, O_WRONLY);
    if (console_fd < 0)
    {
        printf("open %s error\n", con_name);
        return -1;
    }

    return 0;
}

static ssize_t log_console_write(const void *buf, size_t count)
{
    int ret = write(console_fd, buf, count);
    if(ret < 0)
    {
        perror("write err");
    }

    return ret;
}


static int log_std_console(const char *str_tmp)
{
    const char *tmp;
    int dbglevel = DEFAULT_DBG_LEVEL;

    tmp = str_tmp;

    //printf("<4><1><5>");
    // 根据打印级别决定是否打印
    if((str_tmp[0] == '<') && (str_tmp[2] == '>')){
        dbglevel = str_tmp[1] - '0';
        if (dbglevel >= 0 && dbglevel <= 9){
            tmp = tmp + 3;
        }
    }

    if (dbglevel > dbg_limit){
        return -1;
    }

    char str_final[MAX_LOG_BUF_LEN];
    switch (dbglevel) {
    case 5:
        sprintf(str_final, "\033[36m%s\033[0m\r\n", tmp);
        break;
    case 4:
        sprintf(str_final, "\033[33m%s\033[0m\r\n", tmp);
        break;
    case 3:
        sprintf(str_final, "\033[31m%s\033[0m\r\n", tmp);
        break;
    case 2:
        sprintf(str_final, "\033[35m%s\033[0m\r\n", tmp);
        break;
    case 1:
        sprintf(str_final, "\033[35m%s\033[0m\r\n", tmp);
        break;
    case 0:
        sprintf(str_final, "\033[35m%s\033[0m\r\n", tmp);
        break;
    default:
        sprintf(str_final, "%s\r\n", tmp);
        break;
    }

    log_console_write(str_final, strlen(str_final));

    return 0;
}

int __log_console(const char *format, ...)
{
    char str_tmp[MAX_LOG_BUF_LEN];
    va_list arg;
    int len;

    va_start(arg, format);
    len = vsnprintf(str_tmp, MAX_LOG_BUF_LEN, format, arg);
    va_end(arg);
    str_tmp[len] = '\0';
    log_std_console(str_tmp + 3);

    return 0;
}
